/*
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

/*
 *
 *
 *
 *
 *
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

package java.util.concurrent.atomic;

import sun.misc.Unsafe;

/**
 * AtomicBoolean是通过原子方式更新 boolean 值。
 * AtomicBoolean用于诸如原子更新标志之类的应用程序，但是不能替换boolean类使用
 * 原理：
 * AtomicBoolean 内部持有了一个 volatile变量修饰的value，
 * 底层通过对象在内存中的偏移量(valueOffset)对应的旧值与当前值进行比较，
 * 相等则更新并返回true；否则返回false。
 * <p>
 * 即CAS的交换思想. AtomicBoolean 内部可以保证，在高并发情况下，同一时刻只有一个线程对变量修改成功。
 */
public class AtomicBoolean implements java.io.Serializable {
    private static final long serialVersionUID = 4654671469794556979L;

    // CAS
    private static final Unsafe unsafe = Unsafe.getUnsafe();

    // 对象在内存中映射偏移量
    private static final long valueOffset;

    // static静态代码块，随AtomicBoolean类加载时执行一次，可见valueOffset针对所有对象在内存中的映射
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                    (AtomicBoolean.class.getDeclaredField("value"));
        } catch (Exception ex) {
            throw new Error(ex);
        }
    }

    private volatile int value;


    // 构造器
    public AtomicBoolean(boolean initialValue) {
        value = initialValue ? 1 : 0;
    }


    public AtomicBoolean() {
    }

    public final boolean get() {
        return value != 0;
    }


    /**
     * 原子性地比较当前值与预期值，并设置新值
     * 此方法确保在多线程环境下，变量的读取-比较-设置操作是原子的，即不可中断的
     *
     * @param expect 预期值，方法会比较当前值与这个预期值是否相等
     * @param update 新值，如果当前值与预期值相等，则将当前值设置为这个新值
     * @return 如果当前值与预期值相等，并且成功设置新值，则返回true；否则返回false
     */
    public final boolean compareAndSet(boolean expect, boolean update) {
        // 将布尔值转换为整型，以便进行CAS操作
        int e = expect ? 1 : 0;
        int u = update ? 1 : 0;
        // 使用Unsafe类提供的方法执行CAS操作，以原子方式更新值
        return unsafe.compareAndSwapInt(this, valueOffset, e, u);
    }


    /**
     * 使用弱一致性比较并设置值
     * 该方法尝试以弱一致性的方式比较当前值与预期值，如果相等，则将值更新为指定的新值
     * 弱一致性意味着在某些情况下，此方法可能返回false，即使比较和设置操作实际上成功了
     *
     * @param expect 预期的当前值
     * @param update 要更新的新值
     * @return 如果当前值等于预期值，并且成功更新为新值，则返回true；否则返回false
     */
    public boolean weakCompareAndSet(boolean expect, boolean update) {
        // 将布尔值转换为整型，以便进行CAS操作
        int e = expect ? 1 : 0;
        int u = update ? 1 : 0;
        // 使用Unsafe类进行比较并设置操作，这是实现CAS的关键步骤
        return unsafe.compareAndSwapInt(this, valueOffset, e, u);
    }

    /**
     * 使用标准的set方法来设置变量的值
     * 该方法会立即更新变量的值，并可能触发内存屏障操作
     * @param newValue 要设置的新值，true或false
     */
    public void set(boolean newValue) {
        // 将布尔值转换为整型值，true转换为1，false转换为0
        int v = newValue ? 1 : 0;
    }

    /**
     * 使用lazySet方法来设置变量的值
     * 该方法是最终的(final)，不能被子类覆盖
     * 该方法使用有序写操作，不会立即刷新到主内存，适用于不需要立即可见性的场景
     * @param newValue 要设置的新值，true或false
     */
    public final void lazySet(boolean newValue) {
        // 将布尔值转换为整型值，true转换为1，false转换为0
        int v = newValue ? 1 : 0;
        // 使用Unsafe类的putOrderedInt方法，高效地设置变量的值
        // this表示当前对象实例
        // valueOffset是变量相对于对象起始地址的偏移量
        // v是要设置的新值
        unsafe.putOrderedInt(this, valueOffset, v);
    }


    /**
     * 原子地获取并设置布尔值
     * 该方法确保在获取当前值并在设置新值的过程中不会被其他线程中断
     * @param newValue 要设置的新布尔值
     * @return 返回设置新值之前旧的布尔值
     */
    public final boolean getAndSet(boolean newValue) {
        boolean prev;
        do {
            // 获取当前值
            prev = get();
            // 尝试设置新值，如果设置失败则重新获取当前值并再次尝试
            // 这是一个循环操作，直到成功设置新值为止
        } while (!compareAndSet(prev, newValue));
        // 返回旧的值
        return prev;
    }


    public String toString() {
        return Boolean.toString(get());
    }

}
